﻿using System;
using biz.ritter.javapi.lang;
using biz.ritter.javapi.util;
using biz.ritter.javapi.lang.reflect;
using Nofs.Net.nofs.metadata.interfaces;
using biz.ritter.javapi.lang.annotation;


namespace Nofs.Net.AnnotationDriver
{
    public class GetterSetterPair : IGetterSetterPair
    {
        private readonly Object _obj;
        private readonly Method _getter;
        private readonly Method _setter;

        public GetterSetterPair(Object obj, Class parameterType, Class annotationType)
        {
            _obj = obj;
            _getter = FindGetterMethod(parameterType, annotationType, obj.getClass());
            _setter = FindSetterMethod(parameterType, annotationType, obj.getClass());
        }

        private static LinkedList<Method> GetMethodsWithAnnotation(Class objectType, Class annotationType)
        {
            LinkedList<Method> methods = new LinkedList<Method>();
            foreach (Method m in objectType.getMethods())
            {
                foreach (IAnnotation a in m.getAnnotations())
                {
                    if (a.annotationType().getClass() == annotationType)
                    {
                        methods.add(m);
                        break;
                    }
                }
            }
            return methods;
        }

        private static Method FindGetterMethod(Class parameterType, Class annotationType, Class objectType)
        {
            foreach (Method method in GetMethodsWithAnnotation(objectType, annotationType))
            {
                if (method.getReturnType() == parameterType && method.getParameterTypes().Length == 0)
                {
                    return method;
                }
            }
            return null;
        }

        private static Method FindSetterMethod(Class parameterType, Class annotationType, Class objectType)
        {
            foreach (Method method in GetMethodsWithAnnotation(objectType, annotationType))
            {
                if (method.getReturnType() == typeof(void).getClass() && method.getParameterTypes().Length == 1 && method.getParameterTypes()[0] == parameterType)
                {
                    return method;
                }
            }
            return null;
        }

        //@Override
        public Object Getter() //throws IllegalArgumentException, IllegalAccessException, InvocationTargetException 
        {
            return _getter.invoke(_obj, (Object[])null);
        }

        //@Override
        public bool GetterExists()
        {
            return _getter != null;
        }

        //@Override
        public void Setter(Object value) //throws IllegalArgumentException, IllegalAccessException, InvocationTargetException 
        {
            _setter.invoke(_obj, value);
        }

        //@Override
        public bool SetterExists()
        {
            return _setter != null;
        }

    }
}
